package com.lingnan.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lingnan.dto.InterviewDto;
import com.lingnan.entity.dto.InterviewInvitationRequest;
import com.lingnan.entity.po.Company;
import com.lingnan.entity.po.Interview;
import com.lingnan.entity.po.JobSeeker;
import com.lingnan.entity.vo.Result;
import com.lingnan.exception.MyException;
import com.lingnan.feign.NotificationFeignClient;
import com.lingnan.feign.ResumeFeignClient;
import com.lingnan.feign.UserFeignClient;
import com.lingnan.mapper.JobSeekMapper;
import com.lingnan.service.InterviewService;
import com.lingnan.mapper.InterviewMapper;
import com.lingnan.dto.InterviewQueryParam;
import com.lingnan.utils.LoginContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
* @author abc20
* @description 针对表【interview(面试安排记录表)】的数据库操作Service实现
* @createDate 2025-07-16 10:16:50
*/
@Service
@Slf4j
public class InterviewServiceImpl extends ServiceImpl<InterviewMapper, Interview>
    implements InterviewService{

    @Autowired
    private InterviewMapper interviewMapper;
@Autowired
    private JobSeekMapper jobSeekMapper;

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private ResumeFeignClient resumeFeignClient;

    @Autowired
    private NotificationFeignClient notificationFeignClient;


    @Override
    public IPage<InterviewDto> getListByQueryParam(int pageNum, int pageSize, InterviewQueryParam queryParam) {
        // 创建分页对象
        Page<Interview> page = new Page<>(pageNum, pageSize);

        // 构建查询条件
        LambdaQueryWrapper<Interview> queryWrapper = new LambdaQueryWrapper<>();

        if (queryParam != null) {
            // 求职者姓名模糊查询
            if (StringUtils.isNotBlank(queryParam.getSeekerName())) {
                queryWrapper.like(Interview::getSeekerName, queryParam.getSeekerName());
            }

            // 职位名称模糊查询
            if (StringUtils.isNotBlank(queryParam.getJobName())) {
                queryWrapper.like(Interview::getJobName, queryParam.getJobName());
            }

            // 面试状态精确查询
            if (queryParam.getStatus() >= 0) {
                queryWrapper.eq(Interview::getStatus, queryParam.getStatus());
            }

            // 时间范围查询逻辑
            buildTimeRangeQuery(queryWrapper, queryParam);
        }

        // 按面试时间倒序排列
        queryWrapper.orderByDesc(Interview::getInterviewTime);

        // 执行分页查询
        IPage<Interview> interviewPage = this.page(page, queryWrapper);

        // 转换为DTO
        IPage<InterviewDto> resultPage = new Page<>(pageNum, pageSize, interviewPage.getTotal());
        List<InterviewDto> dtoList = interviewPage.getRecords().stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());

        resultPage.setRecords(dtoList);
        return resultPage;
    }

    /**
     * 构建时间范围查询条件
     */
    private void buildTimeRangeQuery(LambdaQueryWrapper<Interview> queryWrapper, InterviewQueryParam queryParam) {
        Date startTime = queryParam.getInterviewTime();
        Date endTime = queryParam.getInterviewEndTime();

        if (startTime != null && endTime != null) {
            // 查询在指定时间范围内的面试（面试时间段与查询时间段有交集）
            // 条件：面试开始时间 <= 查询结束时间 AND 面试结束时间 >= 查询开始时间
            queryWrapper.le(Interview::getInterviewTime, endTime)
                    .ge(Interview::getInterviewEndTime, startTime);
        } else if (startTime != null) {
            // 只指定了开始时间，查询面试结束时间 >= 指定开始时间的记录
            queryWrapper.ge(Interview::getInterviewEndTime, startTime);
        } else if (endTime != null) {
            // 只指定了结束时间，查询面试开始时间 <= 指定结束时间的记录
            queryWrapper.le(Interview::getInterviewTime, endTime);
        }
    }

    /**
     * 实体转DTO
     */
    private InterviewDto convertToDto(Interview interview) {
        InterviewDto dto = new InterviewDto();
        dto.setId(interview.getId());
        dto.setSeekerName(interview.getSeekerName());
        dto.setJobName(interview.getJobName());
        dto.setHrName(interview.getHrName());
        dto.setInterviewTime(interview.getInterviewTime());
        dto.setInterviewEndTime(interview.getInterviewEndTime());
        dto.setLocation(interview.getLocation());
        dto.setStatus(interview.getStatus());
        dto.setCreatedAt(interview.getCreatedAt());

        return dto;
    }



    @Override
//    @GlobalTransactional
    public boolean updateInterviewStatus(Interview request) {
        try {
            // 1. 验证面试记录是否存在
            Interview existingInterview = this.getById(request.getId());
            if (existingInterview == null) {
                log.error("面试记录不存在，ID: {}", request.getId());
                return false;
            }

            // 2. 验证状态值是否合法 (0:待面试 1:通过 2:未通过)
            if (request.getStatus() < 0 || request.getStatus() > 2) {
                log.error("面试状态值不合法，status: {}", request.getStatus());
                return false;
            }

            // 3. 更新面试状态和反馈信息
            LambdaUpdateWrapper<Interview> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Interview::getId, request.getId())
                    .set(Interview::getStatus, request.getStatus());

            // 如果有面试官反馈，一并更新
            if (request.getFeedback() != null) {
                updateWrapper.set(Interview::getFeedback, request.getFeedback());
            }

            // 如果状态不是待面试，设置面试结束时间
            if (request.getStatus() != 0) {
                updateWrapper.set(Interview::getInterviewEndTime, LocalDateTime.now());
            }

            boolean updateResult = this.update(updateWrapper);

            if (updateResult) {
                log.info("面试状态更新成功，面试ID: {}, 新状态: {}", request.getId(), request.getStatus());

                // 4. 异步调用远程服务更新求职者投递记录状态
                // 这里预留远程调用逻辑，可以使用异步方式避免影响主业务
                updateJobApplicationStatus((long) existingInterview.getApplicationId(), request.getStatus());

                return true;
            } else {
                log.error("面试状态更新失败，面试ID: {}", request.getId());
                return false;
            }

        } catch (Exception e) {
            log.error("更新面试状态异常，面试ID: {}, 错误信息: {}", request.getId(), e.getMessage(), e);
            MyException.cast("更新面试状态失败");
        }
        return true;
    }

    /**
     * 远程调用更新求职者投递记录状态
     * 这里先预留接口，后续可以实现具体的远程调用逻辑
     */
    @Async  // 标记为异步方法
    protected void updateJobApplicationStatus(Long applicationId, Integer interviewStatus) {
        try {
            // 可以使用 @Async 注解实现异步调用
            // 面试状态映射关系：
            // 面试通过(1) -> 投递状态可能更新为"待终面"或"录用"
            // 面试未通过(2) -> 投递状态更新为"面试未通过"

            log.info("准备更新投递记录状态，applicationId: {}, interviewStatus: {}", applicationId, interviewStatus);
            if(interviewStatus==1){
                interviewStatus=4;//投递记录显示已通过
            }
            if(interviewStatus==2){
                interviewStatus=3;//投递记录显示未通过
            }

            // 远程调用代码，更新投递记录的状态
            resumeFeignClient.updateApplicationStatus(applicationId, Long.valueOf(interviewStatus));

        } catch (Exception e) {
            log.error("远程调用更新投递记录状态失败，applicationId: {}, 错误信息: {}", applicationId, e.getMessage(), e);
            // 这里可以考虑放入消息队列重试，避免影响主业务
        }
    }

    @Override
    public boolean addInterviewerFeedback(Integer interviewId, String feedback) {
        try {
            // 1. 验证面试记录是否存在
            Interview existingInterview = this.getById(interviewId);
            if (existingInterview == null) {
                log.error("面试记录不存在，ID: {}", interviewId);
                return false;
            }

            // 2. 验证反馈内容
            if (feedback == null || feedback.trim().isEmpty()) {
                log.error("反馈内容不能为空");
                return false;
            }

            // 3. 更新反馈字段
            LambdaUpdateWrapper<Interview> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Interview::getId, interviewId)
                    .set(Interview::getFeedback, feedback.trim());

            boolean updateResult = this.update(updateWrapper);

            if (updateResult) {
                log.info("面试官反馈添加成功，面试ID: {}", interviewId);
                return true;
            } else {
                log.error("面试官反馈添加失败，面试ID: {}", interviewId);
                return false;
            }

        } catch (Exception e) {
            log.error("添加面试官反馈异常，面试ID: {}, 错误信息: {}", interviewId, e.getMessage(), e);
            return false;
        }
    }
    @Override
    public Interview createInterview(Interview interview) {
        //插入数据库
        interviewMapper.insert(interview);
        //获取公司信息
        Company company = userFeignClient.getCompanyByHrUserId(Long.parseLong(LoginContextHolder.getLoginId()));
        //根据传入的求职者姓名查求职者用户id
        JobSeeker jobSeeker = jobSeekMapper.selectOne(new LambdaQueryWrapper<JobSeeker>().eq(JobSeeker::getRealName, interview.getSeekerName()));
        //发送通知
        InterviewInvitationRequest request = new InterviewInvitationRequest();
        String loginId = LoginContextHolder.getLoginId();
        request.setSenderId(Long.valueOf(loginId));
        request.setReceiverId(jobSeeker.getUserId());
        request.setCompanyName(company.getName());
        request.setPosition(interview.getJobName());
        request.setInterviewTime(interview.getInterviewTime().toString());
        request.setAddress(interview.getLocation());
        notificationFeignClient.sendInterviewInvitation(request);
        return interview;
    }

    @Override
    public Interview getInterviewById(Long id) {
        return getById(id);
    }

    @Override
    public List<Interview> getInterviewByHrId(Long id) {
        return list(new QueryWrapper<Interview>().eq("hr_id",id));
    }

    @Override
    public boolean updateInterview(Interview interview) {
        return updateById(interview);
    }

    @Override
    public boolean deleteInterview(Long id) {

        // 查询面试记录
        Interview interview = getById(id);
        if (interview == null) {
            throw new MyException("找不到ID为" + id + "的面试记录");
        }

        // 业务规则校验：只允许删除未开始的面试
        if (interview.getStatus() != 0) {  // 0表示待面试状态
            throw new MyException("只能删除待面试状态的记录，当前状态为：" + interview.getStatus());
        }

        // 执行删除操作
        boolean success = removeById(id);

        // 记录操作日志
//        if (success) {
//            log.debug("成功删除面试记录：ID={}, 关联申请ID={}, HR ID={}",
//                    id, interview.getApplicationId(), interview.getHrId());
//        } else {
//            log.error("删除面试记录失败：ID={}", id);
//        }

        return success;
    }

    @Override
    public List<Interview> getInterviewsByApplicationId(Long applicationId) {
        return this.list(new LambdaQueryWrapper<Interview>().eq(Interview::getApplicationId,applicationId));
    }

    @Override
    public Boolean deleteInterviewsByApplicationId(Long applicationId) {
        return this.remove(new LambdaQueryWrapper<Interview>().eq(Interview::getApplicationId,applicationId));
    }


}




